import type { GiteePageTypeResult } from './types'
import { logger } from '../../../../types/constants'
import { PageRoute } from '../../../abstract/page_route'
import { ToolKit } from '../../../utils/toolkit'
import { GiteePageType } from './types'

export class GiteePage extends PageRoute {
  readonly name: string = 'GiteePage'
  private static instance: GiteePage
  get pageType(): GiteePageType | 'default' {
    return this.getCurrentPageMeta().type
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): GiteePage {
    if (!GiteePage.instance) {
      GiteePage.instance = new GiteePage()
    }
    return GiteePage.instance
  }

  /**
   * 获取当前页面类型
   */
  public getCurrentPageMeta(): GiteePageTypeResult {
    const url = this.getCurrentUrl()
    const path = new URL(url).pathname

    // 404 页面检测
    const notFoundResult = this.detectNotFoundPage()
    if (notFoundResult)
      return notFoundResult

    // 首页
    if (/^\/?$/.test(path)) {
      return { type: GiteePageType.Index }
    }

    if ($('body.projects-site-content').length) {
      // 项目页面
      if (/^\/[^/]+\/[^/]+$/.test(path)) {
        return { type: GiteePageType.Project }
      }
      // 项目页面点击文件后会进入代码视图页面
      else if (/^\/[^/]+\/[^/]+\/blob\//.test(path)) {
        return { type: GiteePageType.CodeView }
      }
    }

    // 历史项目页面
    if ($('#git-project-branch .menu .tab.active[data-tab="commits"]').length) {
      return { type: GiteePageType.HistoryProject }
    }

    // 代码视图页面
    if ($('body:is(.blob-site-content, .tree-site-content)').length) {
      return { type: GiteePageType.CodeView }
    }

    // 基础页面检测
    const pageResult = this.detectPages(path)
    if (pageResult)
      return pageResult

    // 未定义页面
    return { type: GiteePageType.Undefined }
  }

  /**
   * 检测 404 页面
   */
  private detectNotFoundPage(): GiteePageTypeResult | null {
    const pageNotFoundRules = [
      /404.*Not Found/i, // 不区分大小写
    ]

    if (pageNotFoundRules.some(regex => regex.test(document.title))) {
      return { type: GiteePageType.NotFound }
    }

    return null
  }

  /**
   * 检测其他功能页面
   */
  private detectPages(basePath: string): GiteePageTypeResult | null {
    const pageDetectors: Array<[RegExp, (...args: any[]) => GiteePageTypeResult]> = [
      // 提交记录
      [/^\/([^/]+)\/([^/]+)\/commits\/([^/]+)\/?$/, () => {
        return { type: GiteePageType.Commits }
      }],
    ]

    for (const [regex, handler] of pageDetectors) {
      const match = basePath.match(regex)
      if (match) {
        return handler(match)
      }
    }

    return null
  }

  /**
   * 转换 URL 为原始格式
   */
  convertUrlToRawUrl(url: string, originalValue: string): string {
    // 替换路径中的 xxx 为 raw
    return ToolKit.browser.url.replacePathPart(url, 3, 'raw', {
      validate: currentValue => currentValue === originalValue,
    }) as string
  }

  /**
   * 获取当前项目的 Git 分支
   * @returns Git 分支名称
   */
  getGitBranch(): string {
    return $('#git-project-branch').text().trim()
  }

  /**
   * 获取当前文件的完整路径（包括文件名）
   * @param element 文件元素
   * @returns 完整文件路径
   */
  getFullFilePath(element: HTMLElement | JQuery<HTMLElement>): string {
    const $element = element instanceof HTMLElement ? $(element) : element

    // 获取目录路径
    const directoryPath = this.parseProjectDirectoryPath($element)

    // 获取文件名
    const fileName = this.extractFileName($element)

    // 构建完整路径
    return directoryPath ? `${directoryPath}/${fileName}` : fileName
  }

  /**
   * 解析悬浮文件所在的项目目录路径
   * @param element 悬浮的文件元素
   * @returns 完整的项目目录路径
   */
  parseProjectDirectoryPath(element: HTMLElement | JQuery<HTMLElement>): string {
    const $element = element instanceof HTMLElement ? $(element) : element
    const fileName = this.extractFileName($element)

    try {
      // 获取文件所在的树节点
      const $treeNode = $element.closest('.el-tree > .el-tree-node')

      if ($treeNode.length === 0) {
        logger.warn(`[${this.name}] 未找到文件 '${fileName}' 所在的树节点`)
        return ''
      }

      // 收集所有父级文件夹节点
      const pathSegments: string[] = []
      let currentNode = $treeNode[0]

      // 向上遍历树结构
      while (currentNode) {
        const $current = $(currentNode)

        // 检查是否是文件夹节点
        const isFolder = $current.find('.custom-folder-node').length > 0

        if (isFolder) {
          // 提取文件夹名称
          const folderName = this.extractFolderName($current)
          if (folderName) {
            pathSegments.unshift(folderName) // 添加到路径开头
          }
        }

        // 移动到父级节点
        const $parentNode = $current.closest('.el-tree-node__children').prev('.el-tree-node')

        if ($parentNode.length === 0)
          break

        currentNode = $parentNode[0]
      }

      // 构建完整路径
      return pathSegments.join('/')
    }
    catch (error) {
      logger.error(`${this.name} 解析项目目录路径失败:`, error)
      return ''
    }
  }

  /**
   * 提取文件夹名称
   * @param $treeNode 树节点 jQuery 对象
   * @returns 文件夹名称
   */
  private extractFolderName($treeNode: JQuery<HTMLElement>): string {
    return $treeNode.find('.custom-folder-node > div').text().trim()
  }

  /**
   * 提取文件名
   * @param $element 文件元素
   * @returns 文件名
   */
  private extractFileName($element: JQuery<HTMLElement>): string {
    return $element.text().trim()
  }
}
